// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package tls

import (
	"bytes"
	"container/list"
	"context"
	"crypto"
	"crypto/ecdsa"
	"crypto/ed25519"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha512"
	"crypto/x509"
	"errors"
	"fmt"
	"internal/godebug"
	"io"
	"net"
	"strings"
	"sync"
	"time"
)

const (
	VersionTLS10 = 0x0301
	VersionTLS11 = 0x0302
	VersionTLS12 = 0x0303
	VersionTLS13 = 0x0304

	// 已弃用：SSLv3已被加密破坏，并且不再受此软件包的
	// 支持。见戈朗。org/issue/32716。
	VersionSSL30 = 0x0300
)

const (
	maxPlaintext       = 16384        // 最大明文有效负载长度
	maxCiphertext      = 16384 + 2048 // 最大密文有效负载长度
	maxCiphertextTLS13 = 16384 + 256  // TLS 1.3中的最大密文长度
	recordHeaderLen    = 5            // 记录头长度
	maxHandshake       = 65536        // 我们支持的最大握手（协议最大为16MB）
	maxUselessRecords  = 16           // 连续非前进记录的最大数量
)

// TLS记录类型。wen jian defg
type recordType uint8

const (
	recordTypeChangeCipherSpec recordType = 20
	recordTypeAlert            recordType = 21
	recordTypeHandshake        recordType = 22
	recordTypeApplicationData  recordType = 23
)

const (
	typeHelloRequest        uint8 = 0
	typeClientHello         uint8 = 1
	typeServerHello         uint8 = 2
	typeNewSessionTicket    uint8 = 4
	typeEndOfEarlyData      uint8 = 5
	typeEncryptedExtensions uint8 = 8
	typeCertificate         uint8 = 11
	typeServerKeyExchange   uint8 = 12
	typeCertificateRequest  uint8 = 13
	typeServerHelloDone     uint8 = 14
	typeCertificateVerify   uint8 = 15
	typeClientKeyExchange   uint8 = 16
	typeFinished            uint8 = 20
	typeCertificateStatus   uint8 = 22
	typeKeyUpdate           uint8 = 24
	typeNextProtocol        uint8 = 67  // 不是IANA指定的
	typeMessageHash         uint8 = 254 // 合成消息
)

// TLS压缩类型。
const (
	compressionNone uint8 = 0
)

// TLS分机号
const (
	extensionServerName              uint16 = 0
	extensionStatusRequest           uint16 = 5
	extensionSupportedCurves         uint16 = 10 // TLS 1.3中支持的组，请参阅RFC 8446第4.2.7节
	extensionSupportedPoints         uint16 = 11
	extensionSignatureAlgorithms     uint16 = 13
	extensionALPN                    uint16 = 16
	extensionSCT                     uint16 = 18
	extensionSessionTicket           uint16 = 35
	extensionPreSharedKey            uint16 = 41
	extensionEarlyData               uint16 = 42
	extensionSupportedVersions       uint16 = 43
	extensionCookie                  uint16 = 44
	extensionPSKModes                uint16 = 45
	extensionCertificateAuthorities  uint16 = 47
	extensionSignatureAlgorithmsCert uint16 = 50
	extensionKeyShare                uint16 = 51
	extensionRenegotiationInfo       uint16 = 0xff01
)

// TLS信令密码套件值
const (
	scsvRenegotiation uint16 = 0x00ff
)

// CurveID是椭圆曲线的TLS标识符类型。见
// https:
// 
// 在TLS 1.3中，这种类型称为NamedGroup，但此时此库
// 仅支持基于椭圆曲线的组。见RFC 8446，第4.2.7节。
type CurveID uint16

const (
	CurveP256 CurveID = 23
	CurveP384 CurveID = 24
	CurveP521 CurveID = 25
	X25519    CurveID = 29
)

// TLS 1.3密钥共享。见RFC 8446，第4.2.8节。
type keyShare struct {
	group CurveID
	data  []byte
}

// TLS 1.3 PSK密钥交换模式。见RFC 8446，第4.2.9节。
const (
	pskModePlain uint8 = 0
	pskModeDHE   uint8 = 1
)

// TLS 1.3 PSK标识。可以是会话票证，也可以是对已保存
// 会话的引用。见RFC 8446，第4.2.11节。
type pskIdentity struct {
	label               []byte
	obfuscatedTicketAge uint32
}

// TLS椭圆曲线点格式
// https:
const (
	pointFormatUncompressed uint8 = 0
)

// TLS CertificateStatusType（RFC 3546）
const (
	statusTypeOCSP uint8 = 1
)

// 证书类型（用于CertificateRequestsMSG）
const (
	certTypeRSASign   = 1
	certTypeECDSASign = 64 // ECDSA或EdDSA密钥，请参阅RFC 8422第3节。
)

// 签名算法（用于内部信令）。从225开始，以避免与
// TLS 1.2代码点（RFC 5246，附录A.4.1）重叠，这些代码点与此无关。
const (
	signaturePKCS1v15 uint8 = iota + 225
	signatureRSAPSS
	signatureECDSA
	signatureEd25519
)

// directSigning是一个标准哈希值，表示不应执行预哈希
// 并且应直接对输入进行签名。它是与Ed25519签名方案关联的
// 哈希函数。
var directSigning crypto.Hash = 0

// supportedSignatureAlgorithms包含签名和哈希算法，
// 该代码在TLS 1.2+ClientHello和TLS 1.2+
// CertificateRequest中提供支持。这两个字段被合并以与TLS 1.3匹配。
// 注意，在TLS 1.2中，ECDSA算法不受P-256等的限制。
var supportedSignatureAlgorithms = []SignatureScheme{
	PSSWithSHA256,
	ECDSAWithP256AndSHA256,
	Ed25519,
	PSSWithSHA384,
	PSSWithSHA512,
	PKCS1WithSHA256,
	PKCS1WithSHA384,
	PKCS1WithSHA512,
	ECDSAWithP384AndSHA384,
	ECDSAWithP521AndSHA512,
	PKCS1WithSHA1,
	ECDSAWithSHA1,
}

// helloRetryRequestRandom被设置为服务器Hello 
// 的随机值，以表示消息实际上是HelloRetryRequest。
var helloRetryRequestRandom = []byte{ // 参见RFC 8446第4.1.3节。
	0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
	0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
	0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
	0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C,
}

const (
	// DegrammeCanaryTLS12或DegrammeCanaryTLS11嵌入服务器
	// random作为降级保护，如果服务器能够协商更高版本。见RFC 8446，第4.1.3节。
	downgradeCanaryTLS12 = "DOWNGRD\x01"
	downgradeCanaryTLS11 = "DOWNGRD\x00"
)

// 在测试中设置TestingOnlyForceDowngrade Canary，以强制服务器端使用
// 包括降级Canary，即使它使用的是更高支持的版本。
var testingOnlyForceDowngradeCanary bool

// ConnectionState记录有关连接的基本TLS详细信息。
type ConnectionState struct {
	// Version是连接使用的TLS版本（例如VersionTLS12）。
	Version uint16

	// 握手如果握手结束，则“完成”为真。
	HandshakeComplete bool

	// 如果使用会话票证或类似机制从
	// 上一个会话成功恢复此连接，则DidResume为真。
	DidResume bool

	// CipherSuite是为连接协商的密码套件（例如，
	// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256，TLS_AES_128_GCM_SHA256）。
	CipherSuite uint16

	// NegotiatedProtocol是与ALPN协商的应用协议。
	NegotiatedProtocol string

	// NegotiatedProtocolismual用于表示双方的NPN谈判。
	// 
	// 已弃用：此值始终为真。
	NegotiatedProtocolIsMutual bool

	// ServerName是
	// 客户端发送的服务器名称指示扩展名的值。它在服务器端和客户端都可用。
	ServerName string

	// PeerCertificates是对等方发送的经过解析的证书，其发送顺序为
	// 顺序。第一个元素是验证连接的叶证书
	// 。
	// 
	// 在客户端，它不能为空。在服务器端，它可以是
	// 如果配置为空。ClientAuth不是RequiredOnClientCert或
	// RequiredOnVerifyClientCert。
	PeerCertificates []*x509.Certificate

	// VerifiedChains是一个或多个链的列表，其中第一个元素是
	// PeerCertificates[0]，最后一个元素来自配置。RootCAs（在
	// 客户端）或配置。ClientCAs（在服务器端）。
	// 
	// 在客户端，设置为if Config。不安全的技能验证是错误的。在服务器端，设置为if Config。ClientAuth是VerifyClientCertified 
	// （且对等方提供了证书）或RequiredVerifyClientCert。
	VerifiedChains [][]*x509.Certificate

	// SignedCertificateTimestamps是对等方
	// 通过TLS握手为叶证书（如果有）提供的SCT列表。
	SignedCertificateTimestamps [][]byte

	// OCSPResponse是订书的在线证书状态协议（OCSP）
	// 由对等方为叶证书（如果有）提供的响应。
	OCSPResponse []byte

	// TLSUnique包含“tls唯一”通道绑定值（参见RFC 5929，
	// 3节）。对于TLS 1.3连接和所有
	// 恢复的连接，该值将为零。
	// 
	// 已弃用：在某些情况下，此值对于连接可能不是唯一的。请参阅RFC 5705和
	// RFC 7627以及https:
	TLSUnique []byte

	// ekm是通过ExportKeyingMaterial公开的关闭。
	ekm func(label string, context []byte, length int) ([]byte, error)
}

// ExportKeyingMaterial返回RFC 5705中定义的新
// 切片中导出的关键材料的长度字节。如果context为nil，则不作为
// 种子的一部分使用。如果连接设置为允许通过
// 配置重新协商。重新协商时，此函数将返回一个错误。
func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
	return cs.ekm(label, context, length)
}

// ClientAuthType声明服务器在进行
// TLS客户端身份验证时将遵循的策略。
type ClientAuthType int

const (
	// NoClientCert表示在握手过程中不应请求任何客户端证书
	// 如果发送了任何证书，则不会对其进行验证。
	NoClientCert ClientAuthType = iota
	// RequestClientCert表示在握手过程中应该请求客户端证书
	// 但不要求客户端发送任何
	// 证书。
	RequestClientCert
	// requirenyClientCert表示在握手过程中应请求客户端证书
	// ，并且至少需要一个证书由客户端发送，但该证书不要求有效。
	RequireAnyClientCert
	// VerifyClientCertififGiven表示在握手过程中应该请求客户端证书
	// 但不要求客户端发送
	// 证书。如果客户端确实发送了证书，则需要
	// 有效。
	VerifyClientCertIfGiven
	// RequirementVerifyClientCert表示在握手过程中应请求客户端证书
	// ，并且客户端至少需要发送一个有效证书
	// 。
	RequireAndVerifyClientCert
)

// requiresClientCert报告ClientAuthType是否需要提供客户端
// 证书。
func requiresClientCert(c ClientAuthType) bool {
	switch c {
	case RequireAnyClientCert, RequireAndVerifyClientCert:
		return true
	default:
		return false
	}
}

// ClientSessionState包含客户端恢复TLS 
// 会话所需的状态。
type ClientSessionState struct {
	sessionTicket      []uint8               // 用于与服务器恢复会话的加密票证
	vers               uint16                // 会话协商的TLS版本
	cipherSuite        uint16                // 会话协商的密码套件
	masterSecret       []byte                // 完全握手主密钥，或TLS 1.3 Recoveration_master_secret 
	serverCertificates []*x509.Certificate   // 服务器提交的证书链
	verifiedChains     [][]*x509.Certificate // 我们为验证
	receivedAt         time.Time             // 当从服务器接收会话票证
	ocspResponse       []byte                // 服务器提交的订书OCSP响应
	scts               [][]byte              // 服务器提交的SCT 

	// TLS 1.3领域。
	nonce  []byte    // 由服务器发送的票证当前，以派生PSK 
	useBy  time.Time // 由服务器设置的票证生存期到期
	ageAdd uint32    // 用于发送票证年龄的随机模糊因子
}

// ClientSessionCache是客户端可用于恢复与给定服务器的TLS会话的ClientSessionState对象的缓存。ClientSessionCache 
// 应该期望从不同的
// goroutine并发调用实现。在TLS 1.2之前，只支持基于票证的恢复，不支持
// 基于SessionID的恢复。在TLS 1.3中，它们被合并为PSK模式，即
// 通过此接口支持。
type ClientSessionCache interface {
	// 获取与给定密钥关联的ClientSessionState的搜索。
	// 返回时，如果找到一个，则ok为真。
	Get(sessionKey string) (session *ClientSessionState, ok bool)

	// Put使用给定的密钥将ClientSessionState添加到缓存中。如果TLS 1.3服务器提供多个会话票证，它可能会在一个连接中多次被调用。如果使用nil*ClientSessionState调用，
	// 它应该删除缓存项。
	Put(sessionKey string, cs *ClientSessionState)
}

// go:generate stringer-type=SignatureScheme，CurveID，ClientAuthType-output=common_string。go 

// SignatureScheme识别TLS支持的签名算法。参见
// RFC 8446第4.2.3节。
type SignatureScheme uint16

const (
	// RSASSA-PKCS1-v1_5算法。
	PKCS1WithSHA256 SignatureScheme = 0x0401
	PKCS1WithSHA384 SignatureScheme = 0x0501
	PKCS1WithSHA512 SignatureScheme = 0x0601

	// RSASSA-PSS算法采用公钥加密。
	PSSWithSHA256 SignatureScheme = 0x0804
	PSSWithSHA384 SignatureScheme = 0x0805
	PSSWithSHA512 SignatureScheme = 0x0806

	// ECDSA算法。仅限于TLS 1.3中的特定曲线。
	ECDSAWithP256AndSHA256 SignatureScheme = 0x0403
	ECDSAWithP384AndSHA384 SignatureScheme = 0x0503
	ECDSAWithP521AndSHA512 SignatureScheme = 0x0603

	// EdDSA算法。
	Ed25519 SignatureScheme = 0x0807

	// TLS 1.2的传统签名和哈希算法。
	PKCS1WithSHA1 SignatureScheme = 0x0201
	ECDSAWithSHA1 SignatureScheme = 0x0203
)

// ClientHelloInfo包含来自ClientHello消息的信息，以便在GetCertificate和GetConfigForClient回调中指导应用程序逻辑。
type ClientHelloInfo struct {
	// 密码套件列出了客户支持的密码套件（例如
	// TLS_AES_128_GCM_SHA256，TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256）。
	CipherSuites []uint16

	// ServerName表示客户端为了支持虚拟主机而请求的服务器的名称。只有当
	// 客户端使用SNI时，才会设置ServerName（请参阅RFC 4366，第3.1节）。
	ServerName string

	// SupportedCurves列出了客户端支持的椭圆曲线。
	// 仅当使用支持的椭圆曲线
	// 扩展时，才设置支持的曲线（参见RFC 4492，第5.1.1节）。
	SupportedCurves []CurveID

	// SupportedPoints列出了客户端支持的点格式。
	// 仅当使用支持的点格式扩展
	// 时，才会设置支持的点（请参阅RFC 4492，第5.1.2节）。
	SupportedPoints []uint8

	// SignatureSchemes列出了客户端
	// 愿意验证的签名和哈希方案。只有在使用签名
	// 算法扩展时，才会设置SignatureSchemes（参见RFC 5246，第7.4.1.4.1节）。
	SignatureSchemes []SignatureScheme

	// SupportedProtos列出了客户端支持的应用程序协议。
	// 仅当使用应用层协议
	// 协商扩展时才设置SupportedProtos（请参阅RFC 7301，第3.1节）。
	// 
	// 服务器可以通过设置配置来选择协议。
	// GetConfigForClient返回值中的下一个协议。
	SupportedProtos []string

	// SupportedVersions列出了客户端支持的TLS版本。
	// 对于小于1.3的TLS版本，这是从客户公布的最大
	// 版本推断出来的，因此如果使用最大
	// 之外的值，可能会被拒绝。
	SupportedVersions []uint16

	// Conn是基础网络。康涅狄格接通。不要从该连接中读取或写入
	// 信息；这将导致TLS 
	// 连接失败。wen jian feg
	Conn net.Conn

	config *Config

	// ctx是正在进行的握手的上下文。
	ctx context.Context
}

// Context返回正在进行的握手的上下文。
// 此上下文是传递给HandshakeContext的上下文的子上下文，如果有，则在握手结束时取消。
func (c *ClientHelloInfo) Context() context.Context {
	return c.ctx
}

// CertificateRequestInfo包含来自服务器的
// CertificateRequest消息的信息，该消息用于从客户端请求证书和证明
// 。
type CertificateRequestInfo struct {
	// AcceptableCAs包含零个或多个DER编码的X.501 
	// 可分辨名称。这些是服务器希望返回的证书由其签名的根或中间CA 
	// 的名称。
	// 空片表示服务器没有首选项。
	AcceptableCAs [][]byte

	// SignatureSchemes列出服务器愿意验证的签名方案。
	SignatureSchemes []SignatureScheme

	// Version是为此连接协商的TLS版本。
	Version uint16

	// ctx是正在进行的握手的上下文。
	ctx context.Context
}

// Context返回正在进行的握手的上下文。
// 此上下文是传递给握手文本的上下文的子上下文，
// 如果有，在握手结束时取消。
func (c *CertificateRequestInfo) Context() context.Context {
	return c.ctx
}

// 重新协商支持列举了对TLS 
// 重新协商的不同支持级别。TLS重新协商是在第一次握手后，对连接执行后续
// 握手的行为。这使状态机变得非常复杂，并引发了无数微妙的安全问题。不支持发起重新协商，但支持
// 接受重新协商请求。
// 
// 即使启用，服务器也不能在握手之间更改其身份
// （即，叶证书必须相同）。此外，不允许并发
// 握手和应用程序数据流，因此重新协商只能用于与重新协商同步的协议，如
// HTTPS。
// 
// TLS 1.3中未定义重新协商。
type RenegotiationSupport int

const (
	// 重新协商从不禁用重新协商。
	RenegotiateNever RenegotiationSupport = iota

	// 重新协商EASClient允许远程服务器请求
	// 每个连接重新协商一次。
	RenegotiateOnceAsClient

	// 重新协商自由客户端允许远程服务器重复
	// 请求重新协商。
	RenegotiateFreelyAsClient
)

// 配置结构用于配置TLS客户端或服务器。
// 将一个函数传递给TLS函数后，不能对其进行修改。配置可以重用；tls包也不会修改它。
type Config struct {
	// Rand为nonce和RSA致盲提供了熵源。
	// 如果Rand为零，TLS将使用包
	// crypto/Rand中的加密随机读取器。
	// 读卡器必须能够安全地被多个Goroutine使用。
	Rand io.Reader

	// Time返回当前时间作为自历元起的秒数。
	// 如果时间为零，TLS使用时间。现在
	Time func() time.Time

	// 证书包含一个或多个证书链，以呈现给连接的另一端。自动选择与
	// 对等方要求兼容的第一个证书。
	// 
	// 服务器配置必须设置证书GetCertificate或
	// GetConfigForClient中的一个。进行客户端身份验证的客户端可以设置
	// 证书或GetClientCertificate。
	// 
	// 注意：如果有多个证书，并且它们没有
	// 可选字段叶集，则每次握手时选择证书将产生显著的
	// 性能成本。
	Certificates []Certificate

	// NameToCertificate将证书名称映射到
	// Certificates的元素。请注意，证书名称的格式可以是
	// /'*。实例com’这样的名字就不一定是域名了。
	// 
	// 已弃用：NameToCertificate仅允许将单个
	// 证书与给定名称关联。将此字段保留为nil，让库
	// 从证书中选择第一个兼容链。
	NameToCertificate map[string]*Certificate

	// GetCertificate返回基于给定
	// ClientHelloInfo的证书。只有当客户端提供SNI 
	// 信息或证书为空时，才会调用它。
	// 
	// 如果GetCertificate为nil或返回nil，则证书为
	// 从NameToCertificate检索。如果NameToCertificate为零，将使用
	// 证书的最佳元素。
	GetCertificate func(*ClientHelloInfo) (*Certificate, error)

	// GetClientCertificate，如果不是nil，则在服务器从客户端请求
	// 证书时调用。如果设置，证书的内容将被忽略。
	// 
	// 如果GetClientCertificate返回错误，握手将被
	// 中止，并返回该错误。否则
	// GetClientCertificate必须返回非零证书。如果
	// 证书。证书为空，则不会向服务器发送任何证书。如果服务器无法接受，则可能会中止
	// 握手。
	// 
	// 如果发生重新协商或TLS 1.3正在使用，则同一
	// 连接可能会多次调用GetClientCertificate。
	GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error)

	// GetConfigForClient，如果不是nil，则在从客户机接收到ClientHello 
	// 后调用。它可能会返回一个非nil配置，以便
	// 更改将用于处理此连接的配置。如果
	// 返回的配置为nil，将使用原始配置。此回调返回的
	// 配置随后可能不会被修改。
	// 
	// 如果GetConfigForClient为零，则传递给服务器（）的配置将被
	// 用于所有连接。
	// 
	// 如果在返回的配置上显式设置了SessionTicketKey，或者如果在返回的配置上调用了
	// SetSessionTicketKeys，则将使用这些键。否则，将使用原始配置键（如果自动管理，则可能会使用
	// 旋转）。
	GetConfigForClient func(*ClientHelloInfo) (*Config, error)

	// VerifyPeerCertificate，如果不是nil，则在TLS客户端或服务器进行正常
	// 证书验证后调用。它
	// 接收原始ASN。1对等方提供的证书，以及
	// 正常处理发现的任何验证链。如果返回
	// non nil错误，握手将中止，并导致该错误。
	// 
	// 如果正常验证失败，则握手将在
	// 考虑此回调之前中止。如果正常验证被
	// 设置UnsecureSkipVerify禁用，或者（对于服务器）当ClientAuth为
	// RequestClientCert或RequiredOnClientCert时，则将考虑此回调
	// 但verifiedChains参数始终为零。
	VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error

	// 如果不是nil，则在正常证书
	// 验证和TLS客户端
	// 或服务器验证PeerCertificate之后调用VerifyConnection。如果返回非零错误，则握手被中止
	// 并导致该错误。
	// 
	// 如果正常验证失败，则握手将在
	// 考虑此回调之前中止。无论不安全的SkipVerify或ClientAuth设置如何，此回调将为所有连接
	// 运行。
	VerifyConnection func(ConnectionState) error

	// RootCAs定义客户端在验证服务器证书时使用的根证书授权集
	// 。
	// 如果RootCAs为nil，TLS将使用主机的根CA集。
	RootCAs *x509.CertPool

	// NextProtos是受支持的应用程序级协议列表，按优先顺序排列。如果两个对等点都支持ALPN，则所选的
	// 协议将是此列表中的一个协议，如果没有相互支持的协议，则连接将失败。如果NextProtos为空
	// 或对等方不支持ALPN，则连接将成功，
	// ConnectionState。NegotiatedProtocol将为空。
	NextProtos []string

	// ServerName用于验证返回的
	// 证书上的主机名，除非给出了不安全的skipverify。它还包括
	// 在客户端的握手中，以支持虚拟主机，除非它是
	// IP地址。
	ServerName string

	// ClientAuth确定服务器对
	// TLS客户端身份验证的策略。默认值为NoClientCert。
	ClientAuth ClientAuthType

	// ClientCAs定义了根证书颁发机构
	// 的集合，如果需要，服务器将使用该集合通过ClientAuth中的策略验证客户端证书
	// 的集合。
	ClientCAs *x509.CertPool

	// 不安全SKIPVerify控制客户端是否验证服务器的
	// 证书链和主机名。如果UnsecureSkipVerify为true，则crypto/tls 
	// 接受服务器提供的任何证书以及该
	// 证书中的任何主机名。在这种模式下，TLS容易受到中间机器
	// 攻击，除非使用自定义验证。这只能用于
	// 测试，或与VerifyConnection或VerifyPeerCertificate结合使用。
	InsecureSkipVerify bool

	// CipherSuite是已启用的TLS 1.0–1.2密码套件的列表。
	// 该列表的顺序被忽略。请注意，TLS 1.3密码套件是不可配置的。
	// 
	// 如果CipherSuite为零，则使用安全的默认列表。默认密码
	// 套件可能会随着时间的推移而改变。
	CipherSuites []uint16

	// PreferServerCipherSuite是一个遗留字段，不起作用。
	// 
	// 用于控制服务器是遵循客户端的偏好，还是遵循服务器的偏好。服务器现在根据考虑推断的客户端
	// 密码套件。
	// 硬件、服务器硬件和安全性的逻辑选择相互支持的最佳
	// 
	// 已弃用：已忽略PreferServerCipherSuite。
	PreferServerCipherSuites bool

	// SessionTicketsDisabled可以设置为true以禁用会话票证和
	// PSK（恢复）支持。请注意，在客户端上，会话票证支持为
	// 如果ClientSessionCache为nil，则也将禁用。
	SessionTicketsDisabled bool

	// SessionTicketKey用于TLS服务器提供会话恢复。
	// 参见RFC 5077和RFC 8446的PSK模式。如果为零，则在第一次服务器握手之前，将用随机数据填充
	// 。
	// 
	// 已弃用：如果此字段保留为零，会话票证密钥将每天自动旋转，并在七天后丢弃。对于
	// 自定义轮换计划或同步
	// 终止同一主机的连接，请使用SetSessionTicketKeys。
	SessionTicketKey [32]byte

	// ClientSessionCache是TLS的ClientSessionState项缓存
	// 会话恢复。它只供客户使用。
	ClientSessionCache ClientSessionCache

	// MinVersion包含可接受的最低TLS版本。默认情况下，当充当
	// 客户端时，TLS 1.2当前用作最小值，当充当服务器时，TLS 1.0当前用作最小值。TLS 1.0是该软件包作为客户端和服务器支持的最低
	// 版本。
	// 
	// 客户端默认值可以通过
	// 临时恢复为TLS 1.0，包括GODEBUG环境变量中的值“x509sha1=1”。
	// 请注意，该选项将在Go 1.19中删除（但仍将是
	// 可以显式地将该字段设置为VersionTLS10）。
	MinVersion uint16

	// MaxVersion包含可接受的最大TLS版本。
	// 
	// 默认情况下，使用此软件包支持的最高版本，
	// 当前为TLS 1.3。
	MaxVersion uint16

	// CurvePreferences包含将在
	// ECDHE握手中按优先顺序使用的椭圆曲线。如果为空，则将使用默认值
	// 。客户将使用首选项作为
	// 在TLS 1.3中的主要份额的类型。这在未来可能会改变。
	CurvePreferences []CurveID

	// DynamicRecordSizingDisabled禁用TLS记录的自适应大小调整。
	// 如果为true，则始终使用可能的最大TLS记录大小。当
	// 为false时，可能会调整TLS记录的大小，以提高延迟。
	DynamicRecordSizingDisabled bool

	// 重新协商控制支持何种类型的重新协商。
	// 默认值none适用于绝大多数应用程序。
	Renegotiation RenegotiationSupport

	// KeyLogWriter可以选择指定TLS主密钥的目的地
	// 采用NSS密钥日志格式，可用于允许外部程序
	// 如Wireshark解密TLS连接。
	// 请参阅https:
	// 使用KeyLogWriter会损害安全性，只能用于调试。
	KeyLogWriter io.Writer

	// 互斥保护sessionTicketKeys和autoSessionTicketKeys。
	mutex sync.RWMutex
	// sessionTicketKeys包含零个或多个票证密钥。如果设置，则表示
	// 这些键是用SessionTicketKey或SetSessionTicketKeys设置的。
	// 第一个密钥用于新票证，任何后续密钥都可用于对旧票证进行解密。切片内容不受互斥对象
	// 的保护，是不可变的。
	sessionTicketKeys []ticketKey
	// autoSessionTicketKeys与sessionTicketKeys类似，但归
	// 自动旋转逻辑所有。请参阅配置。票钥匙。
	autoSessionTicketKeys []ticketKey
}

const (
	// ticketKeyNameLen是为识别用于加密的密钥而在加密会话票证前面加上的标识符字节数。
	ticketKeyNameLen = 16

	// ticketKeyLifetime是票证密钥保持有效并可用于恢复客户端连接的时间。
	ticketKeyLifetime = 7 * 24 * time.Hour // 7天

	// ticketKeyRotation是服务器旋转用于新票证的会话票证密钥
	// 的频率。
	ticketKeyRotation = 24 * time.Hour
)

// ticketKey是会话票证密钥的内部表示形式。
type ticketKey struct {
	// keyName是一个不透明的字节字符串，用于标识会话
	// ticket key。它在每一个会议记录中都以明文形式公开。
	keyName [ticketKeyNameLen]byte
	aesKey  [16]byte
	hmacKey [16]byte
	// created是创建此票证密钥的时间。请参阅配置。票钥匙。
	created time.Time
}

// ticketKeyFromBytes将会话的外部表示形式转换为ticketKey。在外部，会话票证密钥是32个随机
// 字节，此函数将其扩展为足够的名称和密钥材料。
func (c *Config) ticketKeyFromBytes(b [32]byte) (key ticketKey) {
	hashed := sha512.Sum512(b[:])
	copy(key.keyName[:], hashed[:ticketKeyNameLen])
	copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16])
	copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32])
	key.created = c.time()
	return key
}

// maxSessionTicketLifetime是TLS 1.3会话允许的最大生存期
// 票证，以及我们为发送的票证设置的生存期。
const maxSessionTicketLifetime = 7 * 24 * time.Hour

// Clone返回c的浅克隆，如果c为nil，则返回nil。克隆TLS客户端或服务器同时使用的
// 配置是安全的。
func (c *Config) Clone() *Config {
	if c == nil {
		return nil
	}
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	return &Config{
		Rand:                        c.Rand,
		Time:                        c.Time,
		Certificates:                c.Certificates,
		NameToCertificate:           c.NameToCertificate,
		GetCertificate:              c.GetCertificate,
		GetClientCertificate:        c.GetClientCertificate,
		GetConfigForClient:          c.GetConfigForClient,
		VerifyPeerCertificate:       c.VerifyPeerCertificate,
		VerifyConnection:            c.VerifyConnection,
		RootCAs:                     c.RootCAs,
		NextProtos:                  c.NextProtos,
		ServerName:                  c.ServerName,
		ClientAuth:                  c.ClientAuth,
		ClientCAs:                   c.ClientCAs,
		InsecureSkipVerify:          c.InsecureSkipVerify,
		CipherSuites:                c.CipherSuites,
		PreferServerCipherSuites:    c.PreferServerCipherSuites,
		SessionTicketsDisabled:      c.SessionTicketsDisabled,
		SessionTicketKey:            c.SessionTicketKey,
		ClientSessionCache:          c.ClientSessionCache,
		MinVersion:                  c.MinVersion,
		MaxVersion:                  c.MaxVersion,
		CurvePreferences:            c.CurvePreferences,
		DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
		Renegotiation:               c.Renegotiation,
		KeyLogWriter:                c.KeyLogWriter,
		sessionTicketKeys:           c.sessionTicketKeys,
		autoSessionTicketKeys:       c.autoSessionTicketKeys,
	}
}

// 如果SessionTicketKey是
// 为向后兼容而随机设置的，但未使用，则将其设置为SessionTicketKey的前缀。
var deprecatedSessionTicketKey = []byte("DEPRECATED")

// initLegacySessionTicketKeyRLocked确保旧版SessionTicketKey字段为
// 如果为空则随机化，否则将从中填充SessionTicketKey。
func (c *Config) initLegacySessionTicketKeyRLocked() {
	// 如果SessionTicketKey已经定义为我们不推荐使用的字符串，
	// 或者如果它是由用户定义的，但SessionTicketKey已经设置，则不要写入。
	if c.SessionTicketKey != [32]byte{} &&
		(bytes.HasPrefix(c.SessionTicketKey[:], deprecatedSessionTicketKey) || len(c.sessionTicketKeys) > 0) {
		return
	}

	// 我们需要写入一些数据，所以获取一个独占锁并重新检查任何条件。
	c.mutex.RUnlock()
	defer c.mutex.RLock()
	c.mutex.Lock()
	defer c.mutex.Unlock()
	if c.SessionTicketKey == [32]byte{} {
		if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
			panic(fmt.Sprintf("tls: unable to generate random session ticket key: %v", err))
		}
		// 在开头写下不推荐使用的前缀，这样我们就知道我们创建了
		// 它。此带有不推荐前缀的密钥不会用作实际的
		// 会话票证密钥，只有在应用程序
		// 出于某种原因重新使用它时，才会随机化。
		copy(c.SessionTicketKey[:], deprecatedSessionTicketKey)
	} else if !bytes.HasPrefix(c.SessionTicketKey[:], deprecatedSessionTicketKey) && len(c.sessionTicketKeys) == 0 {
		c.sessionTicketKeys = []ticketKey{c.ticketKeyFromBytes(c.SessionTicketKey)}
	}

}

// ticketKeys返回此连接的ticketKeys。
// 如果configForClient显式设置了密钥，则将返回这些密钥。否则，将使用c上的键，如果自动管理，
// 可能会旋转。
// 在轮换期间，任何过期的会话票证密钥都将从
// c.sessionTicketKeys中删除。如果当前为
// 加密票证的会话票证密钥（即c.sessionTicketKeys中的第一个票证密钥）
// 不新鲜，则将创建一个新的会话票证密钥
// 并将其添加到c.SessionicketKeys之前。
func (c *Config) ticketKeys(configForClient *Config) []ticketKey {
	// 如果ConfigForClient回调返回的配置带有显式设置的
	// 键，请使用这些键，否则只需使用原始配置即可。
	if configForClient != nil {
		configForClient.mutex.RLock()
		if configForClient.SessionTicketsDisabled {
			return nil
		}
		configForClient.initLegacySessionTicketKeyRLocked()
		if len(configForClient.sessionTicketKeys) != 0 {
			ret := configForClient.sessionTicketKeys
			configForClient.mutex.RUnlock()
			return ret
		}
		configForClient.mutex.RUnlock()
	}

	c.mutex.RLock()
	defer c.mutex.RUnlock()
	if c.SessionTicketsDisabled {
		return nil
	}
	c.initLegacySessionTicketKeyRLocked()
	if len(c.sessionTicketKeys) != 0 {
		return c.sessionTicketKeys
	}
	// 密钥足够新鲜的常见情况下的快速路径。
	if len(c.autoSessionTicketKeys) > 0 && c.time().Sub(c.autoSessionTicketKeys[0].created) < ticketKeyRotation {
		return c.autoSessionTicketKeys
	}

	// autoSessionTicketKeys通过自动旋转进行管理。
	c.mutex.RUnlock()
	defer c.mutex.RLock()
	c.mutex.Lock()
	defer c.mutex.Unlock()
	// 重新检查条件，以防在获得新锁后发生变化。
	if len(c.autoSessionTicketKeys) == 0 || c.time().Sub(c.autoSessionTicketKeys[0].created) >= ticketKeyRotation {
		var newKey [32]byte
		if _, err := io.ReadFull(c.rand(), newKey[:]); err != nil {
			panic(fmt.Sprintf("unable to generate random session ticket key: %v", err))
		}
		valid := make([]ticketKey, 0, len(c.autoSessionTicketKeys)+1)
		valid = append(valid, c.ticketKeyFromBytes(newKey))
		for _, k := range c.autoSessionTicketKeys {
			// 在旋转当前键的同时，删除所有过期的键。
			if c.time().Sub(k.created) < ticketKeyLifetime {
				valid = append(valid, k)
			}
		}
		c.autoSessionTicketKeys = valid
	}
	return c.autoSessionTicketKeys
}

// SetSessionTicketKeys更新服务器的会话票证密钥。
// 
// 创建新票据时将使用第一个密钥，而所有密钥都可以用于解密票据。在
// 服务器运行时调用此函数可以安全地旋转会话票证密钥。如果键为空，函数
// 将死机。
// 
// 调用此函数将关闭自动会话票证密钥旋转。
// 
// 如果多台服务器正在终止同一主机的连接，它们应该
// 所有服务器都具有相同的会话票证密钥。如果会话票证密钥泄漏，以前记录的和将来使用这些密钥的TLS连接可能会受到破坏。
func (c *Config) SetSessionTicketKeys(keys [][32]byte) {
	if len(keys) == 0 {
		panic("tls: keys must have at least one key")
	}

	newKeys := make([]ticketKey, len(keys))
	for i, bytes := range keys {
		newKeys[i] = c.ticketKeyFromBytes(bytes)
	}

	c.mutex.Lock()
	c.sessionTicketKeys = newKeys
	c.mutex.Unlock()
}

func (c *Config) rand() io.Reader {
	r := c.Rand
	if r == nil {
		return rand.Reader
	}
	return r
}

func (c *Config) time() time.Time {
	t := c.Time
	if t == nil {
		t = time.Now
	}
	return t()
}

func (c *Config) cipherSuites() []uint16 {
	if c.CipherSuites != nil {
		return c.CipherSuites
	}
	return defaultCipherSuites
}

var supportedVersions = []uint16{
	VersionTLS13,
	VersionTLS12,
	VersionTLS11,
	VersionTLS10,
}

// 可调试TLS10启用TLS 1.0。见第45428期。
var debugEnableTLS10 = godebug.Get("tls10default") == "1"

// roleClient和roleServer旨在调用支持的版本和父级
// 在调用站点上更具可读性。
const roleClient = true
const roleServer = false

func (c *Config) supportedVersions(isClient bool) []uint16 {
	versions := make([]uint16, 0, len(supportedVersions))
	for _, v := range supportedVersions {
		if (c == nil || c.MinVersion == 0) && !debugEnableTLS10 &&
			isClient && v < VersionTLS12 {
			continue
		}
		if c != nil && c.MinVersion != 0 && v < c.MinVersion {
			continue
		}
		if c != nil && c.MaxVersion != 0 && v > c.MaxVersion {
			continue
		}
		versions = append(versions, v)
	}
	return versions
}

func (c *Config) maxSupportedVersion(isClient bool) uint16 {
	supportedVersions := c.supportedVersions(isClient)
	if len(supportedVersions) == 0 {
		return 0
	}
	return supportedVersions[0]
}

// supportedVersionsFromMax返回从
// 旧版最大版本值派生的受支持版本的列表。请注意，只返回此
// 库支持的版本。任何较新的对等机都将使用supportedVersions。
func supportedVersionsFromMax(maxVersion uint16) []uint16 {
	versions := make([]uint16, 0, len(supportedVersions))
	for _, v := range supportedVersions {
		if v > maxVersion {
			continue
		}
		versions = append(versions, v)
	}
	return versions
}

var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521}

func (c *Config) curvePreferences() []CurveID {
	if c == nil || len(c.CurvePreferences) == 0 {
		return defaultCurvePreferences
	}
	return c.CurvePreferences
}

func (c *Config) supportsCurve(curve CurveID) bool {
	for _, cc := range c.curvePreferences() {
		if cc == curve {
			return true
		}
	}
	return false
}

// mutualVersion返回要使用的协议版本，给定对等方的播发
// 版本。优先级被赋予对等优先顺序。
func (c *Config) mutualVersion(isClient bool, peerVersions []uint16) (uint16, bool) {
	supportedVersions := c.supportedVersions(isClient)
	for _, peerVersion := range peerVersions {
		for _, v := range supportedVersions {
			if v == peerVersion {
				return v, true
			}
		}
	}
	return 0, false
}

var errNoCertificates = errors.New("tls: no certificates configured")

// getCertificate返回给定ClientHelloInfo的最佳证书，
// 默认为c.Certificates的第一个元素。
func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) {
	if c.GetCertificate != nil &&
		(len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) {
		cert, err := c.GetCertificate(clientHello)
		if cert != nil || err != nil {
			return cert, err
		}
	}

	if len(c.Certificates) == 0 {
		return nil, errNoCertificates
	}

	if len(c.Certificates) == 1 {
		// 只有一个选择，所以做任何工作都没有意义。
		return &c.Certificates[0], nil
	}

	if c.NameToCertificate != nil {
		name := strings.ToLower(clientHello.ServerName)
		if cert, ok := c.NameToCertificate[name]; ok {
			return cert, nil
		}
		if len(name) > 0 {
			labels := strings.Split(name, ".")
			labels[0] = "*"
			wildcardName := strings.Join(labels, ".")
			if cert, ok := c.NameToCertificate[wildcardName]; ok {
				return cert, nil
			}
		}
	}

	for _, cert := range c.Certificates {
		if err := clientHello.SupportsCertificate(&cert); err == nil {
			return &cert, nil
		}
	}

	// 如果没有匹配项，请返回第一个证书。
	return &c.Certificates[0], nil
}

// 如果提供的证书受发送ClientHello的客户端
// 支持，则SupportsCertificate返回零。否则，它将返回一个错误
// 描述不兼容的原因。
// 
// 如果此ClientHelloInfo被传递给GetConfigForClient或GetCertificate 
// 回调，则此方法将考虑相关的配置。请注意，
// 如果GetConfigForClient返回不同的配置，则更改不能是
// 按此方法核算。
// 
// 此函数将调用x509。ParseCertificate，除非设置了c.Leaf，否则这可能会导致
// 产生巨大的性能成本。
func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error {
	// 注意，我们目前不支持证书颁发机构，也不支持
	// 签名算法\证书，也不检查链上的
	// 签名的算法（无论如何都是应该的，请参阅RFC 8446，
	// 第4.4.2.2节）。

	config := chi.config
	if config == nil {
		config = &Config{}
	}
	vers, ok := config.mutualVersion(roleServer, chi.SupportedVersions)
	if !ok {
		return errors.New("no mutually supported protocol versions")
	}

	// 如果客户端指定了他们试图连接的名称，则
	// 证书需要对其有效。如果证书和连接支持静态RSA密钥交换，则返回nil，否则不支持。
	if chi.ServerName != "" {
		x509Cert, err := c.leaf()
		if err != nil {
			return fmt.Errorf("failed to parse certificate: %w", err)
		}
		if err := x509Cert.VerifyHostname(chi.ServerName); err != nil {
			return fmt.Errorf("certificate is not valid for requested server name: %w", err)
		}
	}

	// 支持静态RSA的逻辑与
	// 支持签名密钥交换的逻辑是完全不相交的，所以我们只是将其作为备用项进行检查。
	supportsRSAFallback := func(unsupported error) error {
		// TLS 1.3放弃了对静态RSA密钥交换的支持。
		if vers == VersionTLS13 {
			return unsupported
		}
		// 静态RSA密钥交换的工作原理是使用
		// RSA私钥解密挑战，而不是通过签名，因此请检查私钥是否实现了
		// 加密。解密程序，比如rsa。PrivateKey有。
		if priv, ok := c.PrivateKey.(crypto.Decrypter); ok {
			if _, ok := priv.Public().(*rsa.PublicKey); !ok {
				return unsupported
			}
		} else {
			return unsupported
		}
		// 最后，需要一个使用静态
		// RSA密钥交换而不是ECDHE的互密码套件。
		rsaCipherSuite := selectCipherSuite(chi.CipherSuites, config.cipherSuites(), func(c *cipherSuite) bool {
			if c.flags&suiteECDHE != 0 {
				return false
			}
			if vers < VersionTLS12 && c.flags&suiteTLS12 != 0 {
				return false
			}
			return true
		})
		if rsaCipherSuite == nil {
			return unsupported
		}
		return nil
	}

	// 如果客户端发送了签名算法扩展，请确保它支持
	// 我们可以使用此证书和TLS版本的方案。
	if len(chi.SignatureSchemes) > 0 {
		if _, err := selectSignatureScheme(vers, c, chi.SignatureSchemes); err != nil {
			return supportsRSAFallback(err)
		}
	}

	// 在TLS 1.3中，我们这样做是因为受支持的_组仅与
	// ECDHE计算相关，点格式协商被删除，密码套件仅与AEAD选择相关，并且静态RSA不存在。
	if vers == VersionTLS13 {
		return nil
	}

	// 我们唯一支持的签名密钥交换是ECDHE。
	if !supportsECDHE(config, chi.SupportedCurves, chi.SupportedPoints) {
		return supportsRSAFallback(errors.New("client doesn't support ECDHE, can only use legacy RSA key exchange"))
	}

	var ecdsaCipherSuite bool
	if priv, ok := c.PrivateKey.(crypto.Signer); ok {
		switch pub := priv.Public().(type) {
		case *ecdsa.PublicKey:
			var curve CurveID
			switch pub.Curve {
			case elliptic.P256():
				curve = CurveP256
			case elliptic.P384():
				curve = CurveP384
			case elliptic.P521():
				curve = CurveP521
			default:
				return supportsRSAFallback(unsupportedCertificateError(c))
			}
			var curveOk bool
			for _, c := range chi.SupportedCurves {
				if c == curve && config.supportsCurve(c) {
					curveOk = true
					break
				}
			}
			if !curveOk {
				return errors.New("client doesn't support certificate curve")
			}
			ecdsaCipherSuite = true
		case ed25519.PublicKey:
			if vers < VersionTLS12 || len(chi.SignatureSchemes) == 0 {
				return errors.New("connection doesn't support Ed25519")
			}
			ecdsaCipherSuite = true
		case *rsa.PublicKey:
		default:
			return supportsRSAFallback(unsupportedCertificateError(c))
		}
	} else {
		return supportsRSAFallback(unsupportedCertificateError(c))
	}

	// 确保有一个相互支持的密码套件可用于
	// 此证书。然后，密码套件选择将应用
	// reverse中的逻辑来选择它。另请参见serverHandshakeState。cipherSuiteOk。
	cipherSuite := selectCipherSuite(chi.CipherSuites, config.cipherSuites(), func(c *cipherSuite) bool {
		if c.flags&suiteECDHE == 0 {
			return false
		}
		if c.flags&suiteECSign != 0 {
			if !ecdsaCipherSuite {
				return false
			}
		} else {
			if ecdsaCipherSuite {
				return false
			}
		}
		if vers < VersionTLS12 && c.flags&suiteTLS12 != 0 {
			return false
		}
		return true
	})
	if cipherSuite == nil {
		return supportsRSAFallback(errors.New("client doesn't support any cipher suites compatible with the certificate"))
	}

	return nil
}

// 如果提供的证书受发送证书请求的服务器
// 支持，则SupportsCertificate返回零。否则，它将返回一个错误
// 描述不兼容的原因。
func (cri *CertificateRequestInfo) SupportsCertificate(c *Certificate) error {
	if _, err := selectSignatureScheme(cri.Version, c, cri.SignatureSchemes); err != nil {
		return err
	}

	if len(cri.AcceptableCAs) == 0 {
		return nil
	}

	for j, cert := range c.Certificate {
		x509Cert := c.Leaf
		// 如果这不是叶节点，或者如果
		// 链，则解析证书。叶是零。
		if j != 0 || x509Cert == nil {
			var err error
			if x509Cert, err = x509.ParseCertificate(cert); err != nil {
				return fmt.Errorf("failed to parse certificate #%d in the chain: %w", j, err)
			}
		}

		for _, ca := range cri.AcceptableCAs {
			if bytes.Equal(x509Cert.RawIssuer, ca) {
				return nil
			}
		}
	}
	return errors.New("chain is not signed by an acceptable CA")
}

// BuildNameToCertificate从每个叶
// 。
// 证书的CommonName和SubjectAlternateName字段解析c.证书并生成c.NameToCertificate 
// 
// 已弃用：NameToCertificate仅允许将单个证书
// 与给定名称关联。将该字段保留为nil，让库从证书中选择第一个
// 兼容链。ABCFDG＊＊＊＊＊＊＊＊／／如果SANS不存在，一些客户端会考虑证书的
func (c *Config) BuildNameToCertificate() {
	c.NameToCertificate = make(map[string]*Certificate)
	for i := range c.Certificates {
		cert := &c.Certificates[i]
		x509Cert, err := cert.leaf()
		if err != nil {
			continue
		}
		if x509Cert.Subject.CommonName != "" && len(x509Cert.DNSNames) == 0 {
			c.NameToCertificate[x509Cert.Subject.CommonName] = cert
		}
		for _, san := range x509Cert.DNSNames {
			c.NameToCertificate[san] = cert
		}
	}
}

const (
	keyLogLabelTLS12           = "CLIENT_RANDOM"
	keyLogLabelClientHandshake = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
	keyLogLabelServerHandshake = "SERVER_HANDSHAKE_TRAFFIC_SECRET"
	keyLogLabelClientTraffic   = "CLIENT_TRAFFIC_SECRET_0"
	keyLogLabelServerTraffic   = "SERVER_TRAFFIC_SECRET_0"
)

func (c *Config) writeKeyLog(label string, clientRandom, secret []byte) error {
	if c.KeyLogWriter == nil {
		return nil
	}

	logLine := []byte(fmt.Sprintf("%s %x %x\n", label, clientRandom, secret))

	writerMutex.Lock()
	_, err := c.KeyLogWriter.Write(logLine)
	writerMutex.Unlock()

	return err
}

// writerMutex保护全球所有的KeylogWriter。它很少启用，
// 并且只用于调试，因此全局互斥可以节省空间。
var writerMutex sync.Mutex

// 证书是由一个或多个证书组成的链，叶优先。
type Certificate struct {
	Certificate [][]byte
	// PrivateKey包含与
	// Leaf中的公钥对应的私钥。这必须实现加密。使用RSA、ECDSA或Ed25519公钥的签名者。
	// 对于TLS 1.2以下的服务器，它还可以实现加密。使用
	// RSA公钥的解密程序。
	PrivateKey crypto.PrivateKey
	// SupportedSignatureAlgorithms是一个可选列表，限制私有密钥可用于的签名算法。
	SupportedSignatureAlgorithms []SignatureScheme
	// OCSPStaple包含一个可选的OCSP响应，它将被提供给请求它的客户端。
	OCSPStaple []byte
	// SignedCertificateTimestamps包含一个可选的已签名
	// 证书时间戳列表，将提供给请求它的客户端。
	SignedCertificateTimestamps [][]byte
	// Leaf是叶子证书的解析形式，可以使用x509初始化。解析证书以减少每次握手处理。如果为nil，
	// 将根据需要解析叶证书。
	Leaf *x509.Certificate
}

// leaf返回解析后的leaf证书，它可以来自c.leaf，也可以通过解析
// 返回相应的c.certificate[0]。
func (c *Certificate) leaf() (*x509.Certificate, error) {
	if c.Leaf != nil {
		return c.Leaf, nil
	}
	return x509.ParseCertificate(c.Certificate[0])
}

type handshakeMessage interface {
	marshal() []byte
	unmarshal([]byte) bool
}

// LRuseSessionCache是一个ClientSessionCache实现，它使用LRU 
// 缓存策略。
type lruSessionCache struct {
	sync.Mutex

	m        map[string]*list.Element
	q        *list.List
	capacity int
}

type lruSessionCacheEntry struct {
	sessionKey string
	state      *ClientSessionState
}

// NewLRUClientSessionCache返回一个ClientSessionCache，其容量为给定的
// 使用LRU策略。如果容量小于1，则使用默认容量
// 代替。
func NewLRUClientSessionCache(capacity int) ClientSessionCache {
	const defaultSessionCacheCapacity = 64

	if capacity < 1 {
		capacity = defaultSessionCacheCapacity
	}
	return &lruSessionCache{
		m:        make(map[string]*list.Element),
		q:        list.New(),
		capacity: capacity,
	}
}

// Put将提供的（sessionKey，cs）对添加到缓存中。如果cs为nil，则对应于sessionKey的条目
// 将从缓存中删除。
func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) {
	c.Lock()
	defer c.Unlock()

	if elem, ok := c.m[sessionKey]; ok {
		if cs == nil {
			c.q.Remove(elem)
			delete(c.m, sessionKey)
		} else {
			entry := elem.Value.(*lruSessionCacheEntry)
			entry.state = cs
			c.q.MoveToFront(elem)
		}
		return
	}

	if c.q.Len() < c.capacity {
		entry := &lruSessionCacheEntry{sessionKey, cs}
		c.m[sessionKey] = c.q.PushFront(entry)
		return
	}

	elem := c.q.Back()
	entry := elem.Value.(*lruSessionCacheEntry)
	delete(c.m, entry.sessionKey)
	entry.sessionKey = sessionKey
	entry.state = cs
	c.q.MoveToFront(elem)
	c.m[sessionKey] = elem
}

// Get返回与给定键关联的ClientSessionState值。如果找不到值，则返回（nil，false）。
func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) {
	c.Lock()
	defer c.Unlock()

	if elem, ok := c.m[sessionKey]; ok {
		c.q.MoveToFront(elem)
		return elem.Value.(*lruSessionCacheEntry).state, true
	}
	return nil, false
}

var emptyConfig Config

func defaultConfig() *Config {
	return &emptyConfig
}

func unexpectedMessageError(wanted, got any) error {
	return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
}

func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlgorithms []SignatureScheme) bool {
	for _, s := range supportedSignatureAlgorithms {
		if s == sigAlg {
			return true
		}
	}
	return false
}
